/**
 * Copyright (C) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.yinglan.shadowimageview;

import com.yinglan.shadowimageview.util.AttrUtil;
import com.yinglan.shadowimageview.util.Constants;
import com.yinglan.shadowimageview.util.Utils;
import ohos.agp.colors.HsvColor;
import ohos.agp.components.AttrSet;
import ohos.agp.components.Component;
import ohos.agp.components.DependentLayout;
import ohos.agp.render.Canvas;
import ohos.agp.render.MaskFilter;
import ohos.agp.render.Paint;
import ohos.agp.render.Path;
import ohos.agp.utils.Color;
import ohos.agp.utils.RectFloat;
import ohos.agp.window.service.DisplayAttributes;
import ohos.app.Context;
import ohos.global.resource.NotExistException;
import ohos.global.resource.WrongTypeException;
import ohos.media.image.PixelMap;
import ohos.media.image.common.Position;

import java.io.IOException;
import java.math.BigDecimal;

/**
 * DependentView
 *
 * @author name
 * @since 2021-03-31
 */
public class DependentView extends DependentLayout implements Component.DrawTask,Component.EstimateSizeListener {
    /**
     * 全部阴影
     */
    public static final int ALL = 0x1111;
    /**
     * 阴影左侧
     */
    public static final int LEFT = 0x0001;
    /**
     * 阴影上方
     */
    public static final int TOP = 0x0010;
    /**
     * 阴影右侧
     */
    public static final int RIGHT = 0x0100;
    /**
     * 阴影下方
     */
    public static final int BOTTOM = 0x1000;
    /**
     * Round
     */
    private static final int ROUND = 20;
    private static final int MPX = 50;
    private static final int MALPHA = 255;
    private int mShadowSide = BOTTOM;
    private int mShadowDy = 0;
    private RectFloat mRectF = new RectFloat();
    private Paint shadowPaint = new Paint();
    private int shadowRound = 0;
    private int shadowColor = 0;

    /** DependentView
     *
     * @param context
     */
    public DependentView(Context context) {
        super(context);
    }

    /** DependentView
     *
     * @param context
     * @param attrSet
     */
    public DependentView(Context context, AttrSet attrSet) {
        super(context, attrSet);
        initView(attrSet);
        setEstimateSizeListener(this);
        addDrawTask(this::onDraw);
    }

    /** DependentView
     *
     * @param context
     * @param attrSet
     * @param styleName
     */
    public DependentView(Context context, AttrSet attrSet, String styleName) {
        super(context, attrSet, styleName);
    }

    private void initView(AttrSet attrs) {
        mShadowSide = AttrUtil.getIntegerValue(attrs, "shadowSide", BOTTOM);
        shadowPaint.setColor(Color.RED);
        shadowPaint.setStyle(Paint.Style.FILL_STYLE);
        shadowPaint.setDither(true);
        shadowPaint.setAntiAlias(true);
    }

    /** setRadius
     *
     * @param radius
     */
    public void setRadius(int radius) {
        shadowRound = radius;
        invalidate();
    }

    @Override
    public boolean onEstimateSize(int i, int i1) {
        int effect = shadowRound + ROUND;
        float rectLeft = 0;
        float rectTop = 0;
        int rectRight = this.getWidth();
        int rectBottom = this.getHeight() + ROUND;
        this.getWidth();
        /**
         * 计算所需的边距值
         */
        if ((mShadowSide & LEFT) == LEFT) {
            rectLeft = effect;
        }
        if ((mShadowSide & TOP) == TOP) {
            rectTop = effect;
        }
        if ((mShadowSide & RIGHT) == RIGHT) {
            rectRight = this.getEstimatedWidth() - (int)effect;
        }
        if ((mShadowSide & BOTTOM) == BOTTOM) {
            rectBottom = this.getEstimatedHeight() - effect;
        }
        if (String.valueOf(mShadowDy) != null) {
            rectBottom = rectBottom - mShadowDy;
        }
        mRectF.left = rectLeft;
        mRectF.top = rectTop;
        mRectF.right = rectRight;
        mRectF.bottom = rectBottom;
        final int paddingbottom = 50;
        this.setPaddingBottom(paddingbottom);
        invalidate();
        return false;
    }

    @Override
    public void onDraw(Component component, Canvas canvas) {
        final float mask = 50f;
        final int strokeWidth = 10;
        postLayout();
        Paint mPaint = new Paint();
        mPaint.setAntiAlias(true);
        mPaint.setStyle(Paint.Style.FILL_STYLE);
        mPaint.setMaskFilter(new MaskFilter(mask, MaskFilter.Blur.OUTER));
        mPaint.setStrokeWidth(strokeWidth);
        mPaint.setColor(new Color(shadowColor));
        Path mPath = new Path();
        final int heightxy1 = 1050;
        final int heighty2 = 1060;
        DisplayAttributes displayAttributes = Utils.getInstance().getScreenPiex(this.getContext());
        if (displayAttributes.scalDensity == Constants.SCALDENSITY) {
            mPath.moveTo(0 + shadowRound, Constants.XCOOL);
            mPath.lineTo(0 + shadowRound, Constants.YCOOL);
            mPath.lineTo(Constants.XCOOL - shadowRound, Constants.YCOOL);
            mPath.lineTo(Constants.XCOOL - shadowRound, Constants.XCOOL);
        } else {
            mPath.moveTo(shadowRound, heightxy1);
            mPath.lineTo(shadowRound, heighty2);
            mPath.lineTo(heightxy1 - shadowRound, heighty2);
            mPath.lineTo(heightxy1 - shadowRound, heightxy1);
        }

        canvas.drawPath(mPath, mPaint); // 直接画阴影效果
    }

    /** setDrawColor
     *
     * @param resId
     * @throws NotExistException
     * @throws WrongTypeException
     * @throws IOException
     */
    public void setDrawColor(int resId) throws NotExistException, WrongTypeException, IOException {
        if (resId != 0) {
            PixelMap pixelMap = Utils.getInstance().getPixelMapFromMedia(getContext(),resId);
            shadowColor = pixelMap.readPixel(new Position(MPX,MPX));
            shadowColor = getDarkerColor(shadowColor);
        }
    }

    private int getDarkerColor(int color) {
        final float zero = 0.5f;
        HsvColor hsv = HsvColor.toHSV(color);
        float hue = new BigDecimal(hsv.getHue()).add(new BigDecimal(zero)).floatValue();
        float saturation = new BigDecimal(hsv.getSaturation()).subtract(new BigDecimal(zero)).floatValue();
        float value = new BigDecimal(hsv.getValue()).subtract(new BigDecimal(zero)).floatValue();
        int darkerColor = HsvColor.toColor(MALPHA,hue,saturation,value);
        return darkerColor;
    }

    public void setImageShadowColor(int color) {
        this.shadowColor = color;
    }
}
